#pragma once

#include <iostream>

namespace command {
    
/// @brief 抽象命令类, 声明执行命令的接口
class AbstractCommand {
public:
    virtual ~AbstractCommand() {}
    virtual void Execute() = 0;
};

/// @brief 命令接收者, 执行命令功能的相关操作，是具体命令对象业务的真正实现者
class Receiver {
public:
    void Action() {
        printf("this is Receiver::Action!\n");
    }
};

/// @brief 具体命令类, 它拥有接收者对象，并通过调用接收者的功能来完成命令要执行的操作
class ConcreteCommand : public AbstractCommand {
public:
    ConcreteCommand() {
        receiver_.reset(new Receiver());
    }
    virtual void Execute() {
        receiver_->Action();
    }

private:
    std::shared_ptr<Receiver> receiver_;
};

/// @brief 命令请求者, 请求的发送者，它通常拥有很多的命令对象，并通过访问命令对象来执行相关请求，它不直接访问接收者
class Invoker{
public:
    Invoker(AbstractCommand* cmd) : cmd_(cmd) {}
    void SetCommand(AbstractCommand* cmd) {
        cmd_ = cmd;
    }
    void Request() {
        cmd_->Execute();
    }

private:
    AbstractCommand* cmd_;
};

} // namespace command

void Test_15_command_impl_1() {
    printf("-------------------- %s --------------------\n", __FUNCTION__);
    std::shared_ptr<command::AbstractCommand> cmd(new command::ConcreteCommand());

    command::Invoker client(cmd.get());
    client.Request();
}

// -------------------- Test_15_command_impl_1 --------------------
// this is Receiver::Action!